• Writing code for computers presents its own set of challenges, but crafting code that humans will interact with is an even more complex endeavor. Erik Bernhardsson emphasizes the intricacies involved in creating frameworks, libraries, APIs, and programming languages that are not only functional but also user-friendly. The process requires a deep understanding of both computer science and the psychology of how users think and learn. To begin with, the onboarding experience is crucial. Bernhardsson argues that getting started with a product should be considered an integral part of the product itself, rather than an afterthought. He highlights the importance of minimizing friction in the setup process, suggesting that developers should aim to make it as easy as possible for users to start using their tools. This is particularly important in a landscape saturated with development tools, where users have limited patience and energy to explore new options. Humans learn best through examples rather than abstract concepts. Bernhardsson critiques the common practice of structuring documentation around core concepts, advocating instead for a focus on practical examples that allow users to see how the tool works in action. By providing a variety of examples, users can find a starting point that resonates with their specific needs, making the learning process more intuitive. The concept of "falling into the pit of success" is another key idea. Bernhardsson notes that users often encounter errors while programming, which can lead to frustration. Therefore, it is essential to design tools that guide users back to success quickly. This can be achieved by providing helpful error messages, code snippets in exceptions, and warnings that anticipate user mistakes. Avoiding conceptual overload is also vital. Each new concept that users must learn adds friction to their experience. Bernhardsson suggests that tools should aim to reduce the number of concepts users need to grasp while still allowing for a wide range of capabilities. He recalls his own experience with React, where a few simple concepts enabled him to build complex applications, illustrating the power of simplicity in design. The "conceptual duck principle" emphasizes the importance of using familiar terminology. By naming new features in a way that aligns with users' existing mental models, developers can significantly reduce the cognitive load required to understand new tools. This approach fosters a smoother learning curve and enhances user experience. Programmability is another critical aspect of user-friendly design. Bernhardsson encourages developers to create frameworks that allow users to manipulate and extend functionality easily. By enabling users to programmatically interact with the tool, developers can tap into users' creativity and encourage innovative uses of the framework. When it comes to defaults and magic in programming tools, Bernhardsson advises caution. While it may be tempting to minimize user input through defaults, this can lead to confusion if users are unaware of the underlying options. He argues for a balance between convenience and clarity, suggesting that tools should be designed to be intuitive without sacrificing the ability to customize. In conclusion, writing code for humans is a multifaceted challenge that requires careful consideration of user experience. Bernhardsson touches on various strategies to enhance developer tools, such as ensuring immutability, avoiding unnecessary scaffolding, and creating fast feedback loops. He reflects on the difficulty of designing for first-time users, likening it to producing a pop song where the creator must continually consider the perspective of a new listener. This complexity is part of what drives Bernhardsson's passion for building developer tools, as he seeks to create experiences that resonate with users and facilitate their success.